package com.devin.oss;


import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.devin.exception.OSSCreateBucketRuntimeException;
import com.devin.exception.OssPutObjectRuntimeException;
import com.devin.service.PutObjectProgressListener;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.testng.annotations.Test;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.UUID;

/**
 *  
 *  @author devin
 *  @date 2020-04-17 10:52
 *  @version 1.0.2
*/

@Slf4j
public class OSSUtil {


    private final static String OSS_END_POINT = "http://oss-cn-hangzhou.aliyuncs.com";
    //OSS 的key值
    private final static String OSS_ACCESS_KEY_ID = "LTAI4G7k4JGeEc55TcfRbLU3";
    //OSS 的secret值
    private final static String OSS_ACCESS_KEY_SECRET = "QujQePurm2g6vX3iBjluL3DYsCh9lk";
    //OSS 的bucket名字
    private final static String OSS_BUCKET_NAME = "devin-le";
    //设置URL过期时间为10年
    private final static Date OSS_URL_EXPIRATION = new Date(System.currentTimeMillis() + 3600 * 1000 * 24 * 365 * 10);


    private volatile static OSSClient instance;

    private OSSUtil() {
    }
    /**
     * 单例
     * @return  OSS工具类实例
     */
    private static OSSClient getOSSClient() {
        if (instance == null) {
            synchronized (OSSUtil.class) {
                if (instance == null) {
                    instance = new OSSClient(OSS_END_POINT, OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET);
                }
            }
        }
        return instance;
    }


    //文件路径的枚举
    public enum FileDirType {
        //电影
        MOVIE("movie"),
        PIC("pic");
        private String dir;

        FileDirType(String dir) {
            this.dir = dir;
        }

        @JsonValue
        public String getDir() {
            return dir;
        }
    }

    /**
     * 当Bucket不存在时创建Bucket
     *
     *                         1.只能包含小写字母、数字和短横线，
     *                         2.必须以小写字母和数字开头和结尾
     *                         3.长度在3-63之间
     */
    private static void createBucket() {
        try {
            if (!OSSUtil.getOSSClient().doesBucketExist(OSS_BUCKET_NAME)) {//判断是否存在该Bucket，不存在时再重新创建
                OSSUtil.getOSSClient().createBucket(OSS_BUCKET_NAME);
            }
        } catch (Exception e) {
            throw new OSSCreateBucketRuntimeException("创建Bucket失败,请核对Bucket名称(规则：只能包含小写字母、数字和短横线，必须以小写字母和数字开头和结尾，长度在3-63之间)");
        }
    }


    /**
     * 上传文件---去除URL中的？后的时间戳
     * @param file 文件
     * @param fileDir 上传到OSS上文件的路径
     * @return 文件的访问地址
     */
    public static String upload(MultipartFile file, FileDirType fileDir) {
        //创建 bucket
        OSSUtil.createBucket();
        String uploadResult;
        //获得文件名
        String fileName = file.getOriginalFilename();


        boolean status = OSSUtil.uploadFile(file, fileDir);
        if(status == false){
            return "fail";
        }

        uploadResult = OSSUtil.getFileUrl(fileName, fileDir);
       /* int firstChar = fileOssURL.indexOf("?");
        if (firstChar > 0) {
            fileOssURL = fileOssURL.substring(0, firstChar);
        }*/
        return uploadResult;
    }



    /**
     * 获得文件路径
     * @param fileName  文件的名
     * @param fileDir  文件在OSS上的路径
     * @return 文件的路径
     */
    private static String getFileUrl(String fileName, FileDirType fileDir) {
        if (StringUtils.isEmpty(fileName)) {
            log.error("{}", "文件地址为空");
            throw new RuntimeException("文件地址为空");
        }

        URL url = OSSUtil.getOSSClient().generatePresignedUrl(OSS_BUCKET_NAME, fileDir.getDir() + "/" + fileName, OSS_URL_EXPIRATION);
        if (url == null) {
            log.error("{}", "获取oss文件URL失败");
//            throw new OSSGeneratePresignedUrlRuntimeException("获取oss文件URL失败");
        }
        return url.toString();
    }



    public static URL getVideoFace(String fileName,FileDirType fileDir){

        // 设置视频截帧操作。  5秒进行操作
        String style = "video/snapshot,t_5000,f_jpg,w_800,h_600";
        // 指定过期时间为一天。
        //        Date expiration = new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 );
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(OSS_BUCKET_NAME,fileDir.getDir() + "/" + fileName , HttpMethod.GET);
        req.setExpiration(OSS_URL_EXPIRATION);
        req.setProcess(style);
        URL signedUrl = OSSUtil.getOSSClient().generatePresignedUrl(req);
        //        System.out.println(signedUrl);

        return signedUrl;
    }



    /**
     * 上传到OSS服务器  如果同名文件会覆盖服务器上的
     * @param file 文件
     * @param fileDir  上传到OSS上文件的路径
     * @return 文件上传成功的状态
     */
    private static boolean uploadFile(MultipartFile file, FileDirType fileDir) {

        boolean status = false;
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());
//        String fileName = String.format(
//                "%s.%s",
//                UUID.randomUUID().toString(),
//                FilenameUtils.getExtension(file.getOriginalFilename()));
        try (InputStream inputStream = file.getInputStream()) {
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(inputStream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(getContentType(FilenameUtils.getExtension("." + file.getOriginalFilename())));
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            //上传文件
            PutObjectRequest putObjectRequest = new PutObjectRequest(OSS_BUCKET_NAME,fileDir.getDir() + "/" + fileName,inputStream,objectMetadata);
            PutObjectResult putResult = OSSUtil.getOSSClient().putObject(putObjectRequest.withProgressListener(new PutObjectProgressListener()));
//                                        .<PutObjectRequest>withProgressListener(new PutObjectProgressListener());;
            if(putResult != null){
                status = true;
//                byte buffer[] = new byte[1024];
//                putResult.getResponse().getContent().read(buffer);
//                log.info("buffer:");
//                log.info(buffer.toString());
//                putResult.getResponse().getContent().close();
            }
        } catch (Exception e) {
            log.error("{}", "上传文件失败");
            throw new OssPutObjectRuntimeException("上传文件失败");

            //            return null;
        }
        return status;
    }


    /*
    *   用于各种方法是否ok
    * */
    @Test
    public void test(){
//        System.out.println(FileDirType.MOVIE);
//        FileDirType.
        URL videoFace = getVideoFace("1.mp4", FileDirType.MOVIE);
        System.out.println(videoFace);
    }
    /**
     * 判断OSS服务文件上传时文件的contentType
     *
     * @param FilenameExtension 文件后缀
     * @return 后缀
     */
    private static String getContentType(String FilenameExtension) {
        if (FilenameExtension.equalsIgnoreCase("bmp")) {
            return "image/bmp";
        }
        if (FilenameExtension.equalsIgnoreCase("gif")) {
            return "image/gif";
        }
        if (FilenameExtension.equalsIgnoreCase("jpeg") ||
                FilenameExtension.equalsIgnoreCase("jpg") ||
                FilenameExtension.equalsIgnoreCase("png")) {
            return "image/jpeg";
        }
        if (FilenameExtension.equalsIgnoreCase("html")) {
            return "text/html";
        }
        if (FilenameExtension.equalsIgnoreCase("txt")) {
            return "text/plain";
        }
        if (FilenameExtension.equalsIgnoreCase("vsd")) {
            return "application/vnd.visio";
        }
        if (FilenameExtension.equalsIgnoreCase("pptx") ||
                FilenameExtension.equalsIgnoreCase("ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (FilenameExtension.equalsIgnoreCase("docx") ||
                FilenameExtension.equalsIgnoreCase("doc")) {
            return "application/msword";
        }
        if (FilenameExtension.equalsIgnoreCase("xml")) {
            return "text/xml";
        }
        if (FilenameExtension.equalsIgnoreCase("mp4")) {
            return "video/mp4";
        }
        if (FilenameExtension.equalsIgnoreCase("flv")) {
            return "video/flv";
        }
        return "image/jpeg";
    }

}
